package com.hup.vd.view.customView;

import com.hup.utils.commons.hardware.SystemUtil;
import com.hup.utils.commons.start.SpringContext;
import com.hup.utils.commons.start.VersionConfig;
import com.hup.utils.swing.customView.BaseUndoText;
import com.hup.utils.swing.customView.FileChooserPanel;
import com.hup.utils.swing.customView.ViewText;
import com.hup.utils.swing.customView.spinner.IntSpinner;
import com.hup.vd.model.config.AppConfig;
import com.hup.vd.model.config.DownloadConfig;
import com.hup.vd.service.m3u8.HtmlUrlHandler;
import lombok.extern.slf4j.Slf4j;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import javax.swing.undo.UndoManager;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.util.Objects;
import java.util.function.Consumer;

/**
 * @author hugan
 * @date 2022/8/13
 */
@Slf4j
public class SettingPanel extends JPanel {
    public JPanel root;
    public JLabel labVersion;
    public ViewText txtConfigDesc;
    //
    public IntSpinner txtMaxDownload;
    public IntSpinner txtPieceThread;
    public IntSpinner txtPieceRetry;
    public IntSpinner txtPieceWaitTime;
    //
    public FileChooserPanel txtChromeDriver;
    public JTextArea txtUserAgent;
    public IntSpinner txtM3u8Retry;
    public IntSpinner txtM3u8Timeout;
    //
    public JCheckBox btnExportChromeLog;
    public JLabel labReboot;
    public JButton btnSave;
    public JButton btnAppDir;
    public JTextField textField1;
    //
    private AppConfig config;

    public SettingPanel() {
        $$$setupUI$$$();
        labReboot.setVisible(false);
        initListener();
    }

    private void initListener() {
        BaseUndoText.initUndo(txtUserAgent, new UndoManager());
        btnExportChromeLog.addActionListener(e -> {
            config.exportChromeLog = btnExportChromeLog.isSelected();
        });
        btnAppDir.addActionListener(e -> SystemUtil.openDir("./"));
        btnSave.addActionListener(e -> {
            boolean needReboot;
            DownloadConfig downloadConfig = config.getDownloadConfig();
            needReboot = saveChange(txtMaxDownload, downloadConfig.parallelTaskCount, newValue -> downloadConfig.parallelTaskCount = newValue);
            needReboot |= saveChange(txtPieceThread, downloadConfig.parallelPieceDownloadCount, newValue -> downloadConfig.parallelPieceDownloadCount = newValue);
            saveChange(txtPieceRetry, downloadConfig.pieceRetryCount, newValue -> downloadConfig.pieceRetryCount = newValue);
            saveChange(txtPieceWaitTime, downloadConfig.pieceRetryWaitTime, newValue -> downloadConfig.pieceRetryWaitTime = newValue);
            boolean changeChromeDriver = saveChange(txtChromeDriver.getSelectedFilePath(), config.getChromeDriverPath(), s -> config.setChromeDriverPath(s));
            if (changeChromeDriver) {
                boolean canReloadConfig = SpringContext.getBean(HtmlUrlHandler.class).canReloadConfig();
                needReboot |= !canReloadConfig;//不能应用配置,则要重启
            }
            saveChange(txtUserAgent.getText(), downloadConfig.userAgent, newValue -> downloadConfig.userAgent = newValue);
            saveChange(txtM3u8Retry, downloadConfig.m3u8RetryCount, newValue -> downloadConfig.m3u8RetryCount = newValue);
            saveChange(txtM3u8Timeout, downloadConfig.m3u8Timeout, newValue -> downloadConfig.m3u8Timeout = newValue);
            config.save();
            log.info("保存.ed={}", downloadConfig);
            if (needReboot) labReboot.setVisible(true);
        });
    }

    /**
     * @return 是否已修改
     */
    private boolean saveChange(IntSpinner spinner, int oldValue, Consumer<Integer> setter) {
        int newValue = spinner.getIntValue();
        if (oldValue == newValue) return false;
        setter.accept(newValue);
        return true;
    }

    /**
     * @return 是否已修改
     */
    private <T> boolean saveChange(T newValue, T oldValue, Consumer<T> setter) {
        if (Objects.equals(newValue, oldValue)) return false;
        setter.accept(newValue);
        return true;
    }

    public void initConfig(AppConfig config) {
        this.config = config;
        VersionConfig versionConfig = SpringContext.getBean(VersionConfig.class);
        labVersion.setText(versionConfig.version);
        labVersion.setToolTipText(versionConfig.buildTime);
        //
        DownloadConfig downloadConfig = config.getDownloadConfig();
        txtConfigDesc.setText("最大等待任务数:" + downloadConfig.waitTaskCount);
        txtMaxDownload.setIntValue(downloadConfig.parallelTaskCount);
        txtPieceThread.setIntValue(downloadConfig.parallelPieceDownloadCount);
        txtPieceRetry.setIntValue(downloadConfig.pieceRetryCount);
        txtPieceWaitTime.setIntValue(downloadConfig.pieceRetryWaitTime);
        txtChromeDriver.setSelectedFilePath(config.getChromeDriverPath());
        txtUserAgent.setText(downloadConfig.userAgent);
        txtM3u8Retry.setIntValue(downloadConfig.m3u8RetryCount);
        txtM3u8Timeout.setIntValue(downloadConfig.m3u8Timeout);
    }

    /**
     * Method generated by IntelliJ IDEA GUI Designer
     * >>> IMPORTANT!! <<<
     * DO NOT edit this method OR call it in your code!
     *
     * @noinspection ALL
     */
    private void $$$setupUI$$$() {
        createUIComponents();
        root.setLayout(new GridBagLayout());
        root.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(8, 0, 8, 0), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
        labVersion = new JLabel();
        labVersion.setHorizontalAlignment(0);
        labVersion.setText("版本");
        GridBagConstraints gbc;
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 4;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        root.add(labVersion, gbc);
        final JLabel label1 = new JLabel();
        label1.setText("最大并行任务数");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 3;
        gbc.anchor = GridBagConstraints.EAST;
        gbc.insets = new Insets(0, 5, 0, 5);
        root.add(label1, gbc);
        txtMaxDownload = new IntSpinner();
        txtMaxDownload.setIntValue(1);
        txtMaxDownload.setMax(50);
        txtMaxDownload.setMin(1);
        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = 3;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(0, 0, 5, 0);
        root.add(txtMaxDownload, gbc);
        final JLabel label2 = new JLabel();
        label2.setText("单任务线程数");
        gbc = new GridBagConstraints();
        gbc.gridx = 2;
        gbc.gridy = 3;
        gbc.anchor = GridBagConstraints.EAST;
        gbc.insets = new Insets(0, 5, 0, 5);
        root.add(label2, gbc);
        txtPieceThread = new IntSpinner();
        txtPieceThread.setIntValue(1);
        txtPieceThread.setMax(8);
        txtPieceThread.setMin(1);
        gbc = new GridBagConstraints();
        gbc.gridx = 3;
        gbc.gridy = 3;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(0, 0, 5, 0);
        root.add(txtPieceThread, gbc);
        final JLabel label3 = new JLabel();
        label3.setText("片段最大重试次数");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 4;
        gbc.anchor = GridBagConstraints.EAST;
        gbc.insets = new Insets(0, 5, 0, 5);
        root.add(label3, gbc);
        txtPieceRetry = new IntSpinner();
        txtPieceRetry.setIntValue(1);
        txtPieceRetry.setMax(10);
        txtPieceRetry.setMin(0);
        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = 4;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(0, 0, 5, 0);
        root.add(txtPieceRetry, gbc);
        final JLabel label4 = new JLabel();
        label4.setText("片段最小重试间隔(ms)");
        gbc = new GridBagConstraints();
        gbc.gridx = 2;
        gbc.gridy = 4;
        gbc.anchor = GridBagConstraints.EAST;
        gbc.insets = new Insets(0, 5, 0, 5);
        root.add(label4, gbc);
        txtPieceWaitTime = new IntSpinner();
        txtPieceWaitTime.setIntValue(100);
        txtPieceWaitTime.setMax(60000);
        txtPieceWaitTime.setMin(100);
        txtPieceWaitTime.setMinCharColumn(12);
        gbc = new GridBagConstraints();
        gbc.gridx = 3;
        gbc.gridy = 4;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(0, 0, 5, 0);
        root.add(txtPieceWaitTime, gbc);
        final JPanel spacer1 = new JPanel();
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 2;
        gbc.gridwidth = 2;
        gbc.weightx = 1.0;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        root.add(spacer1, gbc);
        final JPanel spacer2 = new JPanel();
        gbc = new GridBagConstraints();
        gbc.gridx = 2;
        gbc.gridy = 2;
        gbc.gridwidth = 2;
        gbc.weightx = 1.0;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        root.add(spacer2, gbc);
        txtConfigDesc = new ViewText();
        txtConfigDesc.setText("最大等待任务数: ");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.gridwidth = 4;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.insets = new Insets(0, 8, 0, 0);
        root.add(txtConfigDesc, gbc);
        final JPanel panel1 = new JPanel();
        panel1.setLayout(new GridBagLayout());
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 6;
        gbc.gridwidth = 4;
        gbc.anchor = GridBagConstraints.EAST;
        gbc.fill = GridBagConstraints.VERTICAL;
        root.add(panel1, gbc);
        btnSave = new JButton();
        btnSave.setText("保存配置");
        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = 0;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.ipady = 10;
        gbc.insets = new Insets(8, 8, 0, 0);
        panel1.add(btnSave, gbc);
        btnAppDir = new JButton();
        btnAppDir.setText("程序目录");
        gbc = new GridBagConstraints();
        gbc.gridx = 2;
        gbc.gridy = 0;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.ipady = 10;
        gbc.insets = new Insets(8, 8, 0, 0);
        panel1.add(btnAppDir, gbc);
        labReboot = new JLabel();
        labReboot.setForeground(new Color(-65536));
        labReboot.setText("需要重启程序!!");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.anchor = GridBagConstraints.SOUTHWEST;
        gbc.insets = new Insets(8, 8, 8, 0);
        panel1.add(labReboot, gbc);
        final JPanel panel2 = new JPanel();
        panel2.setLayout(new GridBagLayout());
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 5;
        gbc.gridwidth = 4;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.insets = new Insets(10, 0, 0, 0);
        root.add(panel2, gbc);
        panel2.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "自动抓取m3u8", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
        final JLabel label5 = new JLabel();
        label5.setText("最大重试次数");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 4;
        gbc.gridwidth = 2;
        gbc.anchor = GridBagConstraints.EAST;
        gbc.insets = new Insets(0, 5, 0, 5);
        panel2.add(label5, gbc);
        txtM3u8Retry = new IntSpinner();
        txtM3u8Retry.setIntValue(1);
        txtM3u8Retry.setMax(10);
        txtM3u8Retry.setMin(0);
        gbc = new GridBagConstraints();
        gbc.gridx = 2;
        gbc.gridy = 4;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(0, 0, 5, 0);
        panel2.add(txtM3u8Retry, gbc);
        final JLabel label6 = new JLabel();
        label6.setText("超时时长(ms)");
        gbc = new GridBagConstraints();
        gbc.gridx = 3;
        gbc.gridy = 4;
        gbc.anchor = GridBagConstraints.EAST;
        gbc.insets = new Insets(0, 5, 0, 5);
        panel2.add(label6, gbc);
        txtM3u8Timeout = new IntSpinner();
        txtM3u8Timeout.setIntValue(3000);
        txtM3u8Timeout.setMax(60000);
        txtM3u8Timeout.setMin(3000);
        txtM3u8Timeout.setMinCharColumn(12);
        gbc = new GridBagConstraints();
        gbc.gridx = 4;
        gbc.gridy = 4;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(0, 0, 5, 0);
        panel2.add(txtM3u8Timeout, gbc);
        final JPanel spacer3 = new JPanel();
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.gridwidth = 3;
        gbc.weightx = 1.0;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        panel2.add(spacer3, gbc);
        final JPanel spacer4 = new JPanel();
        gbc = new GridBagConstraints();
        gbc.gridx = 3;
        gbc.gridy = 1;
        gbc.gridwidth = 2;
        gbc.weightx = 1.0;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        panel2.add(spacer4, gbc);
        txtChromeDriver = new FileChooserPanel();
        txtChromeDriver.setLabel("ChromeDriver路径 ");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 2;
        gbc.gridwidth = 5;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.insets = new Insets(0, 5, 5, 0);
        panel2.add(txtChromeDriver, gbc);
        final JLabel label7 = new JLabel();
        label7.setText("userAgent");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 3;
        gbc.anchor = GridBagConstraints.NORTHWEST;
        gbc.insets = new Insets(0, 30, 0, 5);
        panel2.add(label7, gbc);
        txtUserAgent = new JTextArea();
        txtUserAgent.setLineWrap(true);
        txtUserAgent.setRows(2);
        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = 3;
        gbc.gridwidth = 4;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.insets = new Insets(0, 5, 10, 0);
        panel2.add(txtUserAgent, gbc);
        btnExportChromeLog = new JCheckBox();
        btnExportChromeLog.setText("导出chrome请求日志(临时)");
        btnExportChromeLog.setToolTipText("<html>每次加载页面后都导出chrome日志\n<br>用于错误分析,高能耗!!非持久化配置\n<br>目录:\"./logs\"\n</html>");
        gbc = new GridBagConstraints();
        gbc.gridx = 3;
        gbc.gridy = 0;
        gbc.gridwidth = 2;
        gbc.anchor = GridBagConstraints.EAST;
        panel2.add(btnExportChromeLog, gbc);
        textField1 = new JTextField();
        textField1.setEditable(false);
        textField1.setText("  ！");
        textField1.setToolTipText("使用chromeDriver抓取网页中的m3u8,不一定能抓到");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.anchor = GridBagConstraints.WEST;
        panel2.add(textField1, gbc);
    }

    /**
     * @noinspection ALL
     */
    public JComponent $$$getRootComponent$$$() {
        return root;
    }

    private void createUIComponents() {
        root = this;
    }
}
